home *** CD-ROM | disk | FTP | other *** search
/ Shareware Super Platinum 8 / Shareware Super Platinum 8.iso / mac / WIN_PRO / DS-1.ZIP;1 / PREPROC.ZIP / GETTOK.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-10  |  7.3 KB  |  252 lines

  1. /*
  2.  * This files contains routines for getting the "next" token.
  3.  */
  4. #include "../preproc/preproc.h"
  5. #include "../preproc/pproto.h"
  6.  
  7. /*
  8.  * next_tok - get the next raw token. No macros are expanded here (although
  9.  *  the tokens themselves may be the result of a macro expansion initiated
  10.  *  at a "higher" level). Only #line directives are processed here.
  11.  */
  12. struct token *next_tok()
  13.    {
  14.    struct token *t, *t1;
  15.    struct tok_lst *tlst;
  16.    struct char_src *cs;
  17.    struct str_buf *sbuf;
  18.    char *s;
  19.    char *fname;
  20.    int n;
  21.  
  22.    if (src_stack->flag == DummySrc)
  23.       return NULL;    /* source stack is empty - end of input */
  24.  
  25.    /*
  26.     * See if a directive pushed back any tokens.
  27.     */
  28.    if (src_stack->ntoks > 0)
  29.       return src_stack->toks[--src_stack->ntoks];
  30.  
  31.    switch (src_stack->flag) {
  32.       case CharSrc:
  33.          /*
  34.           * Tokens from a raw character "stream".
  35.           */
  36.          t = tokenize();
  37.          if (t != NULL && src_stack->u.cs->f != NULL)
  38.             t->flag |= LineChk;
  39.          if (t != NULL && t->tok_id == PpLine) {
  40.             /*
  41.              * #line directives must be processed here so they are not
  42.              *  put in macros.
  43.              */
  44.             cs = src_stack->u.cs;
  45.             t1 = NULL;
  46.  
  47.             /*
  48.              * Get the line number from the directive.
  49.              */
  50.             advance_tok(&t1);
  51.             if (t1->tok_id != PpNumber)
  52.                errt1(t1, "#line requires an integer argument");
  53.             n = 0;
  54.             for (s = t1->image; *s != '\0'; ++s) {
  55.                if (*s >= '0' && *s <= '9')
  56.                   n = 10 * n + (*s - '0');
  57.                else
  58.                   errt1(t1, "#line requires an integer argument");
  59.                }
  60.  
  61.             /*
  62.              * Get the file name, if there is one, from the directive.
  63.              */
  64.             advance_tok(&t1);
  65.             fname = NULL;
  66.             if (t1->tok_id == StrLit) {
  67.                sbuf = get_sbuf();
  68.                for (s = t1->image; *s != '\0'; ++s) {
  69.                   if (s[0] == '\\' && (s[1] == '\\' || s[1] == '"'))
  70.                      ++s;
  71.                   AppChar(*sbuf, *s);
  72.                   }
  73.                fname = str_install(sbuf);
  74.                rel_sbuf(sbuf);
  75.                advance_tok(&t1);
  76.                }
  77.             if (t1->tok_id != PpDirEnd)
  78.                errt1(t1, "syntax error in #line");
  79.  
  80.             /*
  81.              * Note the effect of the line directive in the character
  82.              *  source. Line number changes are handled as a relative
  83.              *  adjustments to the line numbers of following lines.
  84.              */
  85.             if (fname != NULL)
  86.                cs->fname = fname;
  87.             cs->line_adj = n - cs->line_buf[next_char - first_char + 1];
  88.             if (*next_char == '\n')
  89.                ++cs->line_adj;  /* the next lines contains no characters */
  90.  
  91.             t = next_tok();     /* the caller does not see #line directives */
  92.             }
  93.          break;
  94.  
  95.       case MacExpand:
  96.          /*
  97.           * Tokens from macro expansion.
  98.           */
  99.          t = mac_tok();
  100.          break;
  101.          
  102.       case TokLst:
  103.          /*
  104.           * Tokens from a macro argument.
  105.           */
  106.          tlst = src_stack->u.tlst;
  107.          if (tlst == NULL)
  108.             t = NULL;
  109.          else {
  110.             t = copy_t(tlst->t);
  111.             src_stack->u.tlst = tlst->next;
  112.             }
  113.          break;
  114.  
  115.       case PasteLsts:
  116.          /*
  117.           * Tokens from token Pasting.
  118.           */
  119.          return paste();
  120.       }
  121.  
  122.    if (t == NULL) {
  123.       /*
  124.        * We have exhasted this entry on the source stack without finding
  125.        *  a token to return.
  126.        */
  127.       pop_src();
  128.       return next_tok();
  129.       }
  130.    else
  131.       return t;
  132.    }
  133.  
  134. /*
  135.  * Get the next raw non-white space token, freeing token that the argument
  136.  *  used to point to.
  137.  */
  138. novalue nxt_non_wh(tp)
  139. struct token **tp;
  140.    {
  141.    register struct token *t;
  142.  
  143.    t = next_tok();
  144.    while (t != NULL && t->tok_id == WhiteSpace) {
  145.       free_t(t);
  146.       t = next_tok();
  147.       }
  148.    free_t(*tp);
  149.    *tp = t;
  150.    }
  151.  
  152. /*
  153.  * advance_tok - skip past white space after expanding macros and
  154.  *  executing preprocessor directives. This routine may only be
  155.  *  called from within a preprocessor directive because it assumes
  156.  *  it will not see EOF (the input routines insure that a terminating
  157.  *  new-line, and thus, for a directive, the PpDirEnd token, will be
  158.  *  seen immediately before EOF).
  159.  */
  160. novalue advance_tok(tp)
  161. struct token **tp;
  162.    {
  163.    struct token *t;
  164.  
  165.    t = interp_dir();
  166.    while (t->tok_id == WhiteSpace) {
  167.       free_t(t);
  168.       t = interp_dir();
  169.       }
  170.    free_t(*tp);
  171.    *tp = t;
  172.    }
  173.  
  174. /*
  175.  * merge_whsp - merge a sequence of white space tokens into one token,
  176.  *  returning it along with the next token. Whether these are raw or
  177.  *  processed tokens depends on the token source function, t_src.
  178.  */
  179. novalue merge_whsp(whsp, next_t, t_src)
  180. struct token **whsp;
  181. struct token **next_t;
  182. struct token *(*t_src)();
  183.    {
  184.    struct token *t1;
  185.    struct str_buf *sbuf;
  186.    int line = -1;
  187.    char *fname = "";
  188.    char *s;
  189.  
  190.    free_t(*whsp);
  191.    t1 = (*t_src)();
  192.    if (t1 == NULL || t1->tok_id != WhiteSpace)
  193.       *whsp  = NULL;   /* no white space here */
  194.    else {
  195.       *whsp = t1;
  196.       t1 = (*t_src)();
  197.       if (t1 != NULL && t1->tok_id == WhiteSpace) {
  198.          if (whsp_image == NoSpelling) {
  199.             /*
  200.              * We don't care what the white space looks like, so
  201.              *  discard the rest of it.
  202.              */
  203.             while (t1 != NULL && t1->tok_id == WhiteSpace) {
  204.                free_t(t1);
  205.                t1 = (*t_src)();
  206.                }
  207.             }
  208.          else {
  209.             /*
  210.              * Must actually merge white space. Put it all white space
  211.              *  in a string buffer and use that as the image of the merged
  212.              *  token. The line number and file name of the new token
  213.              *  is that of the last token whose line number and file
  214.              *  name is important for generating #line directives in
  215.              *  the output.
  216.              */
  217.             sbuf = get_sbuf();
  218.             if ((*whsp)->flag & LineChk) {
  219.                line = (*whsp)->line;
  220.                fname = (*whsp)->fname;
  221.                }
  222.             for (s = (*whsp)->image; *s != '\0'; ++s) {
  223.                AppChar(*sbuf, *s);
  224.                if (*s == '\n' && line != -1)
  225.                   ++line;
  226.                }
  227.             while (t1 != NULL && t1->tok_id == WhiteSpace) {
  228.                if (t1->flag & LineChk) {
  229.                   line = t1->line;
  230.                   fname = t1->fname;
  231.                   }
  232.                for (s = t1->image; *s != '\0'; ++s) {
  233.                   AppChar(*sbuf, *s);
  234.                   if (*s == '\n' && line != -1)
  235.                      ++line;
  236.                   }
  237.                free_t(t1);
  238.                t1 = (*t_src)();
  239.                }
  240.             (*whsp)->image = str_install(sbuf);
  241.             rel_sbuf(sbuf);
  242.             if (t1 != NULL && !(t1->flag & LineChk) && line != -1) {
  243.                t1->flag |= LineChk;
  244.                t1->line = line;
  245.                t1->fname = fname;
  246.                }
  247.             }
  248.          }
  249.       }
  250.    *next_t = t1;
  251.    }
  252.